package com.hzy.alibaba;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * <p>
 * 代码生成器演示
 * </p>
 */
public class MpGenerator {

    /**
     * 自定义模板
     */
    private static final String ENTITY_TEMPLATE_PATH = "/templates/entity.java.ftl";
    private static final String XML_TEMPLATE_PATH = "/templates/mapper.xml.ftl";
    private static final String MAPPER_TEMPLATE_PATH = "/templates/mapper.java.ftl";
    private static final String CONTROLLER_TEMPLATE_PATH = "/templates/controller.java.ftl";
    private static final String SERVICE_IMPL_TEMPLATE_PATH = "/templates/serviceImpl.java.ftl";
    private static final String SERVICE_TEMPLATE_PATH = "/templates/service.java.ftl";

    /**
     * 自定义模块名称
     */
    private static final String outputDir = "d:\\codeGen\\";
    private static final String author = "abc";
    private static final String[] tablePrefix = new String[] { "t_" };
    private static final String base_path = "com.huang";

    /**
     * <p>
     *	main
     *	请注意！运行前请取消 pom.xml 中的 velocity、Freemarker、Beetl 注释（pom文件最下方）
     * </p>
     * @param args
     * @return void
     * @author XinLau
     * @since 2019年2月26日下午5:29:16
     */
    public static void main(String[] args) {
        /**
         * 项目存放路径
         */
        AutoGenerator mpg = new AutoGenerator();

        /**
         * 模板引擎配置		默认Velocity
         */
        //切换成Freemarker
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        setGlobalConfig(mpg);

        setDataSourceConfig(mpg);

        setStrategyConfig(mpg);

        setPackageConfig(mpg);

        setInjectionConfig(mpg);

        /**
         * 生成代码
         */
        mpg.execute();

        /**
         * 打印注入设置【可无】
         */
        System.out.println(mpg.getCfg().getMap().get("Author"));
    }

    public static void setGlobalConfig(AutoGenerator mpg){
        /**
         * 全局 相关配置
         */
        GlobalConfig globalConfig = new GlobalConfig();
        // 生成存放地址
        globalConfig.setOutputDir(outputDir);
        // 是否覆盖已有文件
        globalConfig.setFileOverride(true);
        // 开启 ActiveRecord 模式
        globalConfig.setActiveRecord(true);
        // 是否在XML中添加二级缓存配置（XML 二级缓存）
        globalConfig.setEnableCache(false);
        // 开启 BaseResultMap（XML ResultMap,生成基本的resultMap）
        globalConfig.setBaseResultMap(true);
        // 开启 baseColumnList（XML columList,生成基本的SQL片段）
        globalConfig.setBaseColumnList(true);
        // 开发人员
        globalConfig.setAuthor(author);
        // 是否打开输出目录
        globalConfig.setOpen(true);
        // 指定生成的主键的ID类型
        globalConfig.setIdType(IdType.UUID);
        // 自定义文件命名，注意 %s 会自动填充表实体属性！（各层文件名称方式，例如： %Action 生成 UserAction）
        globalConfig.setMapperName("%sMapper");
        globalConfig.setXmlName("%sMapper");
        globalConfig.setServiceName("%sService");
        globalConfig.setServiceImplName("%sServiceImpl");
        globalConfig.setControllerName("%sController");
        mpg.setGlobalConfig(globalConfig);
    }

    private static void setInjectionConfig(AutoGenerator mpg) {
        /**
         * 注入自定义模板配置，可以在 VM 中使用 cfg.abc 设置的值
         * 自定义模板配置，可以 copy 源码 mybatis-plus/src/main/resources/template 下面内容修改，
         * 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置，也可以自定义模板名称
         */
        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("Author", "Author : " + this.getConfig().getGlobalConfig().getAuthor());
                this.setMap(map);
            }
        };
        //	取消自带（任何一个模块如果设置 空 OR Null 将不生成该模块）
//        TemplateConfig templateConfig = new TemplateConfig();
//        templateConfig.setXml(null);
//        templateConfig.setController(null);
//        templateConfig.setServiceImpl(null);
//        mpg.setTemplate(templateConfig);
        //	设置自定义
        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
        //调整 xml 生成目录
        focList.add(new FileOutConfig(XML_TEMPLATE_PATH) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //	mapper.xml生成路径+名称		如果Entity设置了前后缀、此处注意xml的名称会跟着发生变化
                return "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        //调整 Entity 生成目录
        focList.add(new FileOutConfig(ENTITY_TEMPLATE_PATH) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //	Entity生成路径+名称		如果Entity设置了前后缀、此处名称会跟着发生变化
                return "/" + tableInfo.getEntityName() + StringPool.DOT_JAVA;
            }
        });
        //调整 Mapper 生成目录
        focList.add(new FileOutConfig(MAPPER_TEMPLATE_PATH) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //	Mapper生成路径+名称		如果Entity设置了前后缀、此处注意Mapper的名称会跟着发生变化
                return "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_JAVA;
            }
        });
        //调整Controller生成
        focList.add(new FileOutConfig(CONTROLLER_TEMPLATE_PATH) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //	Controller生成路径+名称		如果Entity设置了前后缀、此处注意Controller的名称会跟着发生变化
                return "/" + tableInfo.getEntityName() + "Controller" + StringPool.DOT_JAVA;
            }
        });
        //调整Service生成
        focList.add(new FileOutConfig(SERVICE_TEMPLATE_PATH) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //	Service生成路径+名称		如果Entity设置了前后缀、此处注意Service的名称会跟着发生变化
                return "/" + tableInfo.getEntityName() + "Service" + StringPool.DOT_JAVA;
            }
        });
        //调整ServiceImpl生成
        focList.add(new FileOutConfig(SERVICE_IMPL_TEMPLATE_PATH) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //	ServiceImpl生成路径+名称		如果Entity设置了前后缀、此处注意ServiceImpl的名称会跟着发生变化
                return "/" + tableInfo.getEntityName() + "ServiceImpl" + StringPool.DOT_JAVA;
            }
        });

        injectionConfig.setFileOutConfigList(focList);
        mpg.setCfg(injectionConfig);
    }

    private static void setPackageConfig(AutoGenerator mpg) {
        /**
         * 包 相关配置
         */
        PackageConfig packageConfig = new PackageConfig();
        //父包名。如果为空，将下面子包名必须写全部， 否则就只需写子包名
        packageConfig.setParent(base_path);
        //Controller包名
        packageConfig.setController("controller");
        //Entity包名
        packageConfig.setEntity("entity");
        //Mapper包名
        packageConfig.setMapper("mapper");
        //Mapper XML包名
        packageConfig.setXml("mapper.xml");
        //Service包名
        packageConfig.setService("service");
        //Service Impl包名
        packageConfig.setServiceImpl("service.impl");
        mpg.setPackageInfo(packageConfig);
    }

    private static void setStrategyConfig(AutoGenerator mpg) {
        /**
         * 数据库表配置（策略配置）
         */
        StrategyConfig strategyConfig = new StrategyConfig();
        // 全局大写命名 ORACLE 注意
        // strategy.setCapitalMode(true);
        // 此处可以修改为您的表前缀（用来去掉不想要的表前缀）
        strategyConfig.setTablePrefix(tablePrefix);
        // 数据库表映射到实体的命名策略（表名生成策略）
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        // 【实体】是否为Lombok模型（默认 false）
        strategyConfig.setEntityLombokModel(true);
        // 是否生成实体时，生成字段注解
        strategyConfig.setEntityTableFieldAnnotationEnable(true);
        // 设置逻辑删除字段
        strategyConfig.setLogicDeleteFieldName("data_status");
        /**
         * "sys_sample",
         * "sys_user_info",
         * "sys_role_info",
         * "sys_position_info",
         * "sys_role_authorization",
         * "sys_organization_info",
         * "sys_menu_resource",
         * "sys_menu_resource_relation",
         * "sys_menu_authorization",
         * "sys_operating_record",
         * "sys_login_history",
         * "sys_data_dictionary",
         * "sys_dictionary_type",
         * "sys_china_city_info"
         */
        //strategyConfig.setEntityBuilderModel(true);// 【实体】是否为构建者模型（默认 false）
        //strategyConfig.setEntityColumnConstant(true);// 【实体】是否生成字段常量（默认 false）
        //strategyConfig.setInclude(new String[]{"sys_sample", "sys_user_info"});//生成指定表；需要包含的表名（与exclude二选一配置）
        //strategyConfig.setExclude(new String[]{"sys_sample", "sys_user_info", "sys_role_info", "sys_role_authorization", "sys_organization_info", "sys_organization_relation", "sys_menu_resource", "sys_menu_resource_relation", "sys_menu_authorization", "sys_operating_record", "sys_login_history", "sys_data_dictionary", "sys_dictionary_type"}); // 排除生成的表
        //strategyConfig.setSuperEntityClass("com.imis.model.SuperEntity");//自定义实体父类
        //strategyConfig.setSuperEntityColumns(new String[] { "id", "data_status", "creator", "creation_time", "last_update_time" });//自定义实体父类，公共字段
        //strategyConfig.setSuperControllerClass("com.baomidou.ant.common.BaseController");// 自定义 controller 父类
        //strategyConfig.setSuperMapperClass("com.baomidou.ant.common.BaseMapper");// 自定义 mapper 父类
        //strategyConfig.setSuperServiceClass("com.baomidou.ant.common.BaseService");// 自定义 service 父类
        //strategyConfig.setSuperServiceImplClass("com.baomidou.ant.common.BaseServiceImpl");// 自定义 service 实现类父类

        mpg.setStrategy(strategyConfig);
    }

    private static void setDataSourceConfig(AutoGenerator mpg) {
        /**
         * 数据源配置
         */
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setTypeConvert(new MySqlTypeConvert() {
            // 自定义数据库表字段类型转换【可选】
            @Override
            public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
                System.out.println("转换类型：" + fieldType);
                //	注意！！processTypeConvert存在默认类型转换，如果不是你要的效果请自定义返回，非如下直接返回
                return super.processTypeConvert(globalConfig, fieldType);
            }
        });
        // 数据库驱动
        dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
        // 数据库账号
        dataSourceConfig.setUsername("root");
        // 数据库密码
        dataSourceConfig.setPassword("123456");
        // 数据库地址
        dataSourceConfig.setUrl("jdbc:mysql://127.0.0.1:3306/hzy-alibaba?characterEncoding=utf8&useSSL=true&serverTimezone=UTC");
        mpg.setDataSource(dataSourceConfig);
    }

    /**
     * <p>
     *	scanner
     *	读取控制台内容
     * </p>
     * @param tableName
     * @return String
     * @author XinLau
     * @since 2019年3月9日下午4:27:43
     */
    @SuppressWarnings("resource")
    public static String scanner(String string){
        Scanner scanner = new Scanner(System.in);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("请输入一个正确的" + string + "：");
        System.out.println(stringBuilder.toString());
        if (scanner.hasNext()) {
            String name = scanner.next();
            if (StringUtils.isNotEmpty(name)) {
                return name;
            }
        }
        throw new MybatisPlusException("请输入正确的" + string + "！！！");
    }

}
